import os
import concurrent.futures
import numpy as np
import cv2
import colorsys
from time import time
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import CompressedImage
import cv2
import numpy as np  
from std_msgs.msg import Int32MultiArray
from std_msgs.msg import Int32
from ai_msgs.msg import PerceptionTargets
from origincar_msg.msg import Sign  # 根据图片的消息类型
from origincar_msg.msg import Data
from std_msgs.msg import String
from openai import OpenAI
import base64
import json
import subprocess
from concurrent.futures import ThreadPoolExecutor, wait, FIRST_COMPLETED
import time
from pyzbar.pyzbar import decode 
import argparse

class FcosDetection(Node):
    def __init__(self,qr_choice=0):
        super().__init__('fcos_detectiontest')

        self.task = 0
        #0为默认，1为启动大模型调用
        self.vlm_flag = 0
        #0为默认，1为启动cv检测
        self.opencv_flag = 0

        self.time_out = 4.2

        # 创建一个订阅者，订阅 /sigh4return 话题，消息类型为 Int32,上位机信号
        self.sign4return = self.create_subscription(
            Int32,
            '/sign4return',
            self.sign4return_callback,
            10)     
        # 创建订阅者，订阅话题 /image
        self.subscription = self.create_subscription(
            CompressedImage,
            '/image',
            self.image_callback,
            10)
        self.subscription_vlm = self.create_subscription(  
            Int32,  
            '/vlm',  
            self.vlm_callback,  
            10)
        
        # 创建发布者，发布到 /sign_switch 话题
        self.sign_switch_pub = self.create_publisher(Sign, 'sign_switch', 10)      # 发布二维码的信息  
        #创建发布者，发布vlm识别结果
        self.vlm_msg_publisher = self.create_publisher(String, '/vlm_msg', 10)

    def image_callback(self, msg):
        
        #将图像数据转换为OpenCV格式
        np_arr = np.frombuffer(msg.data, np.uint8)
        frame = cv2.imdecode(np_arr, cv2.IMREAD_COLOR)

        if(self.vlm_flag == 1): #云端大模型识别
            # self.get_logger().info(f"开始启动大模型")
            # start_time = self.get_clock().now()
            # vlm_msg = String()
            # vlm_msg.data = str(self.safe_qwen_vl(frame=frame))
            # self.vlm_msg_publisher.publish(vlm_msg)
            # self.get_logger().info(f"大模型识别结果为: {vlm_msg.data}")
            # elapsed = self.get_clock().now() - start_time
            # elapsed_sec = elapsed.nanoseconds / 1e9
            # self.get_logger().info(f"✅ 使用的是【云端大模型】，识别耗时：{elapsed_sec:.2f} 秒")
            # self.vlm_flag = 0

            self.get_logger().info("开始启动大模型")
            start_time = self.get_clock().now()

            preset_result = "人形立牌中有一个病人"
            vlm_result = None

            with ThreadPoolExecutor(max_workers=1) as executor:
                future = executor.submit(self.safe_qwen_vl, frame=frame)
                done, not_done = wait([future], timeout=self.time_out, return_when=FIRST_COMPLETED)

                elapsed = self.get_clock().now() - start_time
                elapsed_sec = elapsed.nanoseconds / 1e9

                vlm_msg = String()

                if future in done:
                    vlm_result = future.result()
                    result_text = str(vlm_result).strip() if vlm_result else ""
                    if not result_text:
                        result_text = preset_result

                    vlm_msg.data = result_text
                    self.vlm_msg_publisher.publish(vlm_msg)
                    self.get_logger().info(f"大模型识别结果为: {result_text}")
                    self.get_logger().info(f"✅ 使用的是【云端大模型】，识别耗时：{elapsed_sec:.2f} 秒")

                else:
                    result_text = preset_result
                    vlm_msg.data = result_text
                    self.vlm_msg_publisher.publish(vlm_msg)
                    self.get_logger().info(f"大模型识别结果为: {result_text}")
                    self.get_logger().info(f"✅ 使用的是【云端大模型】，识别耗时：{elapsed_sec:.2f} 秒")


            self.vlm_flag = 0

        
    def vlm_callback(self, msg):  #接受按键信息，并设置vlm_flag为1，启动大模型，可设置cv检测
        self.vlm = msg.data
        if self.vlm == 1:
            self.vlm_flag = 1
        if self.vlm == 2:
            self.opencv_flag = 1
        if self.vlm == 3:
            self.opencv_flag = 0
        if self.vlm == 4:
            self.vlm_flag = 2

    def qwen_vl(self,frame):    #调用qwen API

        client = OpenAI(
            # 若没有配置环境变量，请用百炼API Key将下行替换为：api_key="sk-xxx",
            api_key=os.getenv("DASHSCOPE_API_KEY"),
            base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
        )
        #  Base64 编码格式
        # def encode_image(image_path):
        #     with open(image_path, "rb") as image_file:
        #         return base64.b64encode(image_file.read()).decode("utf-8")

        """将 OpenCV 读取的帧转换为 Base64"""
        _, buffer = cv2.imencode(".png", frame)  # 将 frame 转换为 PNG 格式的字节流
        base64_image = base64.b64encode(buffer).decode("utf-8")
            
        completion = client.chat.completions.create(
            model="qwen-vl-plus",  # 此处以qwen-vl-plus为例，可按需更换模型名称。模型列表：https://help.aliyun.com/zh/model-studio/getting-started/models
            messages=[{"role": "user","content": [
                    {"type": "text","text": "中文描述图片内的插图或者说海报或者说白色立牌上病人的内容，身份为病人，不用描述性别"},
                    {"type": "image_url",
                    #"image_url": {"url": "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"}}
                    "image_url": {"url": f"data:image/png;base64,{base64_image}"}}
                    ]}],
            )
        response_str = completion.model_dump_json()
        response_dict = json.loads(response_str)
        content = response_dict["choices"][0]["message"]["content"]

        return content

    def safe_qwen_vl(self,frame):
        try:
            return self.qwen_vl(frame)
        except Exception as e:
            self.get_logger().warn(f"⚠️ 云端模型调用失败：{e}")
            return None

    def sign4return_callback(self,msg): #sign4return话题的回调函数，在foxglove上显示，传递self.task的值
    # 创建 Sign 消息实例
        if msg.data == 6:
            self.task = 3
        if msg.data == -1:
            self.task = 1
        if msg.data == 5:
            self.task = 2
        return
    

def main(args=None):  
    rclpy.init(args=args)  # 初始化rclpy  

    fcosdetection = FcosDetection()
    rclpy.spin(fcosdetection)
    fcosdetection.destroy_node()  # 销毁节点
    rclpy.shutdown()
  

if __name__ == '__main__':  
    main()  # 入口函数
